using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Org.Loon.Framework.Xna.Game.Core.Geom;
using System.Runtime.CompilerServices;
using Org.Loon.Framework.Xna.Game.Core.Graphics.OpenGL;
using Org.Loon.Framework.Xna.Game.Utils;
using Org.Loon.Framework.Xna.Game.Core;
using Org.Loon.Framework.Xna.Game.Core.Graphics;
using Microsoft.Xna.Framework;

namespace Org.Loon.Framework.Xna.Game.Action.Sprite.Effect
{
    public class SmashEffect
    {

        private Explosion[] explosionsList;

        public enum SmashType
        {
            red, yellow, orange, green, blue, white, star
        }

        class Smash
        {

            internal float velocity;

            internal Vector2f direction;

            internal int moveX;

            internal int moveY;

            internal SmashType type;

            public Smash()
            {
                this.direction = new Vector2f();
            }

            public Smash(int x, int y, float v, Vector2f d, SmashEffect.SmashType p)
            {
                this.moveX = x;
                this.moveY = y;
                this.velocity = v;
                this.direction = d;
                this.type = p;
            }
        }

        public SmashEffect()
            : this(40)
        {

        }

        public SmashEffect(int s)
            : this(s, 0, 2, 2)
        {

        }

        public SmashEffect(int s, int type, int w, int h)
        {
            this.explosionsList = new Explosion[s];
            for (int i = 0; i < this.explosionsList.Length; i++)
            {
                this.explosionsList[i] = new Explosion(s, type, w, h);
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Reset()
        {
            int size = explosionsList.Length;
            for (int i = 0; i < size; i++)
            {
                explosionsList[i].expired = true;
                explosionsList[i].timer = 0;
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void CreateExplosionEffect(int x, int y,
                SmashEffect.SmashType p)
        {
            int i = -1;
            for (int j = 0; j < this.explosionsList.Length; j++)
            {
                if (this.explosionsList[j].expired != true)
                {
                    continue;
                }
                i = j;
                break;
            }
            if (i > -1)
            {
                this.explosionsList[i].CreateExplosion(x, y, p, 40);
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void CreateSmallExplosionEffect(int x, int y)
        {
            CreateSmallExplosionEffect(x, y, SmashType.white, 20);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void CreateSmallExplosionEffect(int x, int y,
                SmashType p, int n)
        {
            int i = -1;
            for (int j = 0; j < this.explosionsList.Length; j++)
            {
                if (this.explosionsList[j].expired != true)
                {
                    continue;
                }
                i = j;
                break;
            }
            if (i > -1)
            {
                this.explosionsList[i].CreateExplosion(x, y, p, n);
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void CreatePlayerExplosionEffect(int x, int y)
        {
            int i = -1;
            for (int j = 0; j < this.explosionsList.Length; j++)
            {
                if (this.explosionsList[j].expired != true)
                    continue;
                i = j;
                break;
            }
            if (i > -1)
            {
                this.explosionsList[i].CreateExplosion(x, y, SmashType.white, 200);
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Update(long elapsedTime)
        {
            int i = 0;
            Explosion explosion;
            for (i = 0; i < this.explosionsList.Length; i++)
            {
                explosion = this.explosionsList[i];
                if (explosion.expired)
                {
                    continue;
                }
                explosion.Update(elapsedTime);
            }
            for (i = 0; i < this.explosionsList.Length; i++)
            {
                explosion = this.explosionsList[i];
                if (explosion.expired)
                {
                    continue;
                }
                if (explosion.timer <= 1500L)
                {
                    continue;
                }
                explosion.expired = true;
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Draw(GLEx g)
        {
            for (int i = 0; i < this.explosionsList.Length; i++)
            {
                if (this.explosionsList[i].expired)
                {
                    continue;
                }
                this.explosionsList[i].Draw(g);
            }
        }

        private class Explosion
        {

            internal int type;

            internal Smash[] smashs;

            internal int width, height;

            internal long timer = 0L;

            internal float alpha = 1.0F;

            internal bool expired = true;

            internal int numSmash;

            public Explosion(int s, int type, int width, int height)
            {
                this.type = type;
                this.width = width;
                this.height = height;
                this.smashs = new Smash[s];
                this.expired = true;
                for (int i = 0; i < this.smashs.Length && i < s; i++)
                {
                    this.smashs[i] = new Smash();
                }
            }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void CreateExplosion(int x, int y, SmashType type,
                    int n)
            {
                this.timer = 0L;
                this.expired = false;
                this.numSmash = n;
                if (smashs.Length != n)
                {
                    smashs = (Smash[])CollectionUtils.Expand(smashs, n);
                    for (int i = 0; i < this.smashs.Length; i++)
                    {
                        this.smashs[i] = new Smash();
                    }
                }
                for (int i = 0; i < n; i++)
                {
                    this.smashs[i].moveX = x;
                    this.smashs[i].moveY = y;
                    this.smashs[i].direction.x = (LSystem.GetRandomBetWeen(-1000,
                            1000) / 1000.0F);
                    this.smashs[i].direction.y = (LSystem.GetRandomBetWeen(-1000,
                            1000) / 1000.0F);
                    this.smashs[i].type = type;
                    this.smashs[i].velocity = (LSystem.GetRandomBetWeen(4, 8) / 10.0F);
                }
            }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Draw(GLEx g)
            {
                this.alpha = ((float)(1500L - this.timer) / 1500.0F);
                if (this.alpha < 0.0F)
                {
                    this.alpha = 0.0F;
                }
                if (this.alpha > 1.0F)
                {
                    this.alpha = 1.0F;
                }
                if (alpha != 1)
                {
                    g.SetAlpha(alpha);
                }
                switch (type)
                {
                    case 0:
                        for (int i = 0; i < this.numSmash; i++)
                        {
                            Smash p = this.smashs[i];
                            if (p.type == SmashType.red)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.Red);
                            }
                            else if (p.type == SmashType.yellow)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.Yellow);
                            }
                            else if (p.type == SmashType.orange)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.Orange);
                            }
                            else if (p.type == SmashType.green)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.Green);
                            }
                            else if (p.type == SmashType.blue)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.Blue);
                            }
                            else if (p.type == SmashType.white)
                            {
                                g.FillRect(p.moveX, p.moveY, width, height, Color.White);
                            }
                        }
                        break;
                    case 1:
                        for (int i = 0; i < this.numSmash; i++)
                        {
                            Smash p = this.smashs[i];
                            if (p.type == SmashType.red)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.Red);
                            }
                            else if (p.type == SmashType.yellow)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.Yellow);
                            }
                            else if (p.type == SmashType.orange)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.Orange);
                            }
                            else if (p.type == SmashType.green)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.Green);
                            }
                            else if (p.type == SmashType.blue)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.Blue);
                            }
                            else if (p.type == SmashType.white)
                            {
                                g.FillOval(p.moveX, p.moveY, width, height, Color.White);
                            }
                        }
                        break;
                }
                g.ResetColor();
                if (alpha != 1)
                {
                    g.SetAlpha(1.0f);
                }
            }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Update(long elapsedTime)
            {
                for (int i = 0; i < this.smashs.Length; i++)
                {
                    Smash p = this.smashs[i];
                    p.moveX += (int)(p.velocity * p.direction.x * elapsedTime);
                    p.moveY += (int)(p.velocity * p.direction.y * elapsedTime);
                }
                this.timer += elapsedTime;
            }

        }
    }
}
